package com.solocredit.finance.data.dev.utils

import android.annotation.SuppressLint
import android.app.ActivityManager
import android.app.usage.StorageStatsManager
import android.content.Context
import android.os.Build
import android.os.Environment
import android.os.StatFs
import android.os.storage.StorageManager
import org.json.JSONObject
import java.io.File
import java.math.BigDecimal
import java.math.RoundingMode
import java.util.UUID

object FlexiMolaSdUtil {

    private const val KEY_TOTAL = "total"
    private const val KEY_AVAILABLE = "available"
    private const val KEY_USED = "used"

    fun talInerSiz(context: Context): String {
        return try {
            val jsonObject = caInerSiz(context)
            jsonObject.getString(KEY_TOTAL)
        } catch (e: Exception) {
            //
            "0"
        }
    }

    fun avalInerSiz(context: Context): String {
        return try {
            val jsonObject = caInerSiz(context)
            jsonObject.getString(KEY_AVAILABLE)
        } catch (e: Exception) {
            //
            "0"
        }
    }

    @SuppressLint("DiscouragedPrivateApi", "UsableSpace")
    private fun caInerSiz(context: Context): JSONObject {
        val unit = 1024f
        val version = Build.VERSION.SDK_INT
        val storeObj = JSONObject()
        try {
            if (version < Build.VERSION_CODES.M) {
                val storageManager =
                    context.getSystemService(Context.STORAGE_SERVICE) as StorageManager
                val getVolumeList = StorageManager::class.java.getDeclaredMethod("getVolumeList")
                val volumeList = getVolumeList.invoke(storageManager) as Array<*>
                var totalSize = 0L
                var availableSize = 0L
                volumeList.first()?.javaClass?.getDeclaredMethod("getPathFile")?.apply {
                    for (volume in volumeList) {
                        val file = invoke(volume) as File?
                        file?.let {
                            totalSize += file.totalSpace
                            availableSize += file.usableSpace
                        }
                    }
                }
                val totalStore = funit(totalSize.toFloat(), unit)
                val availableStore = funit(availableSize.toFloat(), unit)
                storeObj.put(KEY_TOTAL, totalStore)
                storeObj.put(KEY_AVAILABLE, availableStore)
                storeObj.put(KEY_USED, "0")
            } else {
                val storageManager =
                    context.getSystemService(Context.STORAGE_SERVICE) as StorageManager
                var total = 0L
                var used = 0L
                val getVolumes = StorageManager::class.java.getDeclaredMethod("getVolumes")
                val getVolumeInfo = getVolumes.invoke(storageManager) as List<*>
                for (objInfo in getVolumeInfo) {
                    objInfo?.let { obj ->
                        val getType = obj.javaClass.getField("type")
                        val type = getType.getInt(obj)
                        if (type == 1) {
                            var totalSize = 0L
                            if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.O) {
                                val getFsUuid =
                                    obj.javaClass.getDeclaredMethod("getFsUuid")
                                val fsUuid = getFsUuid.invoke(obj) as String?
                                totalSize =
                                    toaSiz(
                                        context,
                                        fsUuid ?: StorageManager.UUID_DEFAULT.toString()
                                    )
                            }
                            val isMountedReadable =
                                obj.javaClass.getDeclaredMethod("isMountedReadable")
                            val readable = isMountedReadable.invoke(obj) as Boolean
                            if (readable) {
                                val file = obj.javaClass.getDeclaredMethod("getPath")
                                val f = file.invoke(obj) as File?
                                f?.let {
                                    if (totalSize == 0L) {
                                        totalSize = f.totalSpace
                                    }
                                    used += totalSize - f.freeSpace
                                    total += totalSize
                                }
                            }
                        } else if (type == 0) {
                            val isMountedReadable =
                                obj.javaClass.getDeclaredMethod("isMountedReadable")
                            val readable = isMountedReadable.invoke(obj) as Boolean
                            if (readable) {
                                val file = obj.javaClass.getDeclaredMethod("getPath")
                                val f = file.invoke(obj) as File?
                                f?.let {
                                    used += f.totalSpace - f.freeSpace
                                    total += f.totalSpace
                                }
                            }
                        }
                    }
                }
                val totalStore = funit(total.toFloat(), unit)
                val usedStore = funit(used.toFloat(), unit)
                val availableStore = funit((total - used).toFloat(), unit)
                storeObj.put(KEY_TOTAL, totalStore)
                storeObj.put(KEY_AVAILABLE, availableStore)
                storeObj.put(KEY_USED, usedStore)
            }
        } catch (e: Exception) {
            //
        }
        return storeObj
    }

    private fun toaSiz(context: Context, fsUuid: String): Long {
        return try {
            if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.O) {
                var id = StorageManager.UUID_DEFAULT
                if (fsUuid.isNotBlank()) {
                    id = UUID.fromString(fsUuid)
                }
                val stats =
                    context.getSystemService(Context.STORAGE_STATS_SERVICE) as StorageStatsManager?
                stats?.getTotalBytes(id) ?: -1
            } else {
                -1
            }
        } catch (e: Exception) {
            //
            -1
        }
    }

    private fun funit(size: Float, unit: Float): String {
        val units = arrayOf("B", "KB", "MB", "GB", "TB")
        var index = 0
        var newSize = size
        while (newSize > unit && index < 4) {
            newSize /= unit
            index++
        }
        val resultDec = BigDecimal(newSize.toDouble())
            .setScale(2, RoundingMode.HALF_UP)
        return "${resultDec.toPlainString()}${units[index]}"
    }

    fun remaiSiz(paramContext: Context): String {
        return try {
            val memoryInfo = ActivityManager.MemoryInfo()
            (paramContext.getSystemService(Context.ACTIVITY_SERVICE) as ActivityManager).getMemoryInfo(
                memoryInfo
            )
            funit(memoryInfo.availMem.toFloat(), 1024f)
        } catch (e: java.lang.Exception) {
            //
            "0"
        }
    }

    fun useSiz(paramContext: Context): String {
        return try {
            val memoryInfo = ActivityManager.MemoryInfo()
            (paramContext.getSystemService(Context.ACTIVITY_SERVICE) as ActivityManager).getMemoryInfo(
                memoryInfo
            )
            val didUsed = memoryInfo.totalMem - memoryInfo.availMem
            funit(didUsed.toFloat(), 1024f)
        } catch (e: java.lang.Exception) {
            //
            "0"
        }
    }

    fun talRSzi(paramContext: Context): String {
        return try {
            val memoryInfo = ActivityManager.MemoryInfo()
            (paramContext.getSystemService(Context.ACTIVITY_SERVICE) as ActivityManager).getMemoryInfo(
                memoryInfo
            )
            funit(memoryInfo.totalMem.toFloat(), 1024f)
        } catch (e: java.lang.Exception) {
            //
            "0"
        }
    }

    fun disRema(): String {
        return try {
            val file = Environment.getDataDirectory()
            val statFs = StatFs(file.path)
            funit(
                (statFs.availableBlocksLong * statFs.blockSizeLong).toFloat(),
                1024f
            )
        } catch (e: java.lang.Exception) {
            //
            "0"
        }
    }

    fun dissee(): String {
        return try {
            val file = Environment.getDataDirectory()
            val statFs = StatFs(file.path)
            val total = statFs.blockCountLong * statFs.blockSizeLong
            val avail = statFs.availableBlocksLong * statFs.blockSizeLong
            val didUsed = total - avail
            funit(didUsed.toFloat(), 1024f)
        } catch (e: java.lang.Exception) {
            //
            "0"
        }
    }

    fun toaDis(): String {
        return try {
            val file = Environment.getDataDirectory()
            val statFs = StatFs(file.path)
            funit(
                (statFs.blockCountLong * statFs.blockSizeLong).toFloat(),
                1024f
            )
        } catch (e: java.lang.Exception) {
            //
            "0"
        }
    }

    fun youKa(): String {
        return if (Environment.getExternalStorageState() == "mounted") {
            "YES"
        } else "NO"
    }

    fun isYoKa(): String {
        return "NO"
    }

    fun toaYoKa(): String {
        return try {
            if (Environment.getExternalStorageState().equals("mounted", ignoreCase = true)) {
                val file = Environment.getExternalStorageDirectory()
                val statFs = StatFs(file.path)
                val l = statFs.blockSizeLong
                return funit((statFs.blockCountLong * l).toFloat(), 1024f)
            }
            "0GB"
        } catch (e: java.lang.Exception) {
            //
            "0GB"
        }
    }
}
